package org.zoffy.security;

import jakarta.annotation.Resource;
import jakarta.servlet.DispatcherType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@EnableWebSecurity
@Configuration
@EnableMethodSecurity
public class WebSecurityConfig {
    @Resource
    private AuthenticationConfiguration authenticationConfiguration;

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new Md5PasswordEncoder();
    }
    @Bean
    public SecurityContextRepository contextRepository(){
        return new HttpSessionSecurityContextRepository();
    }
    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration corsConf = new CorsConfiguration();
        corsConf.addAllowedOriginPattern("*");
        corsConf.addAllowedMethod("*");
        corsConf.addAllowedHeader("*");
        corsConf.setAllowCredentials(true);
        corsConf.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source =new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",corsConf);
        return  source;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http,SecurityContextRepository securityContextRepository,CorsConfigurationSource configurationSource) throws Exception {
        return http.authorizeHttpRequests(request -> {
                    request
                            .dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
                            .requestMatchers("/user/login", "/user/registry").permitAll()
                            .anyRequest().permitAll();
                }).securityContext((securityContext) -> {
                    securityContext.securityContextRepository(securityContextRepository);
                    securityContext.requireExplicitSave(true);
                })
                .cors(cors->{
                    cors.configurationSource(configurationSource);
                })
                .csrf(AbstractHttpConfigurer::disable)
                .build();
    }


    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> {
            web.ignoring().requestMatchers("/user/login", "/user/registry");
        };
    }
}
